import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.StringTokenizer;

public class TCPSpellingServer implements Runnable
{

	public static final String TERMINATION_STRING = "BYE";

	private int threadnumber;
	private Socket tcpsocket;
	private ConcurrentTCPSPellingServer conserver;

	public TCPSpellingServer(ConcurrentTCPSPellingServer concurrentTCPSPelling,
			int the_thread, Socket the_socket)
	{
		this.threadnumber = the_thread;
		this.tcpsocket = the_socket;
		this.conserver = concurrentTCPSPelling;
	}

	public void run()
	{
		try
		{
			String prefix = this.threadnumber + "-----";
			Log.out(prefix + "Session start");
			BufferedReader br = new BufferedReader(new InputStreamReader(
					this.tcpsocket.getInputStream()));
			PrintWriter clientout = new PrintWriter(new BufferedWriter(
					new OutputStreamWriter(this.tcpsocket.getOutputStream())),
					true);
			boolean finished = false;

			while (!finished)
			{
				String str = br.readLine();
				final StringTokenizer stok = new StringTokenizer(str);
				// get the query number for tcp server
				// final int j = stok.countTokens();
				if (str == null)
				{
					Log.err(prefix + "Connection closed unexpectedly");
					finished = true;
				} else if (str.equals(TERMINATION_STRING) || str.length() == 0)
				{
					clientout.println("GOODBYE");
					this.tcpsocket.close();
					finished = true;
					Log.out(prefix + "Connection closed normally");
				} else if (str.indexOf(' ') == -1)
				{
					clientout.println("INVALID");
					this.tcpsocket.close();
					finished = true;
					Log.err(prefix + "Query contains no space");
				} else if (stok.countTokens() > 2)
				{
					clientout.println("INVALID");
					this.tcpsocket.close();
					finished = true;
					Log.err(prefix + "Query contains more than 1 space");
				} else
				{
					int i = 0;
					try
					{
						i = Integer.parseInt(stok.nextToken());
						if (i <= 0)
						{
							Log.err(prefix + "Query with negative number");
						}
					} catch (NumberFormatException e)
					{
						Log.err(prefix + "No query numbers");
						i = -1;
					}

					String word = stok.nextToken();
					if (i > 0)
					{
						Data outputdata = this.conserver.getdata(i, word,
								this.threadnumber);
						final SortedSet<String> wordset = outputdata.getSortedSet();
						final Iterator iterator = wordset.iterator();
						final StringBuffer sb = new StringBuffer();
						// transform the suggestion list into a string and
						// send back to the client side
						if (!outputdata.isInlist())
						{
							while (iterator.hasNext())
							{
								sb.append(iterator.next());
								sb.append(' ');
							}
							clientout.println(i + " NO " + sb.toString());
						} 
						else if (outputdata.isInlist())
						{
							clientout.println(i + " OK ");
						}
						

						Log.out(prefix + "Response sent");

					} else
					{
						clientout.println("INVALID");
						this.tcpsocket.close();
						finished = true;
					}
				}
			}
		} catch (IOException e)
		{
			Log.err(this.threadnumber + "-----unhandled exception" + e);
		}

		try
		{
			this.tcpsocket.close();
			return;
		} catch (IOException e)
		{
			Log.err(this.threadnumber
					+ "-----exception while closing the socket" + e);
		}

	}

}
